package cn.iocoder.yudao.framework.web.controller.error;

import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.autoconfigure.web.servlet.error.DefaultErrorViewResolver;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * 自定义错误控制器，覆盖掉{@link ErrorMvcAutoConfiguration}装配的{@link BasicErrorController}。
 * 具体的“4xx、5xx”等错误页文件定义可参阅{@link DefaultErrorViewResolver}。
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @see ErrorMvcAutoConfiguration#basicErrorController
 * @see <a href="https://blog.csdn.net/qq_41366629/article/details/121566198">SpringBoot返回前端状态码404、500异常处理，全部返回200</a>
 */
@Slf4j
@Tag(name = "出错")
@Controller
public class CustomErrorController implements ErrorController {
    private final ErrorInfoBuilder errorInfoBuilder;

    public CustomErrorController(ErrorInfoBuilder errorInfoBuilder) {
        this.errorInfoBuilder = errorInfoBuilder;
    }

    @SneakyThrows
    @RequestMapping(value = "${server.error.path:${error.path:/error}}", produces = MediaType.TEXT_HTML_VALUE)
    @PermitAll
    public void errorHtml(HttpServletRequest request, HttpServletResponse response) {
        ErrorInfoVO errorInfo = errorInfoBuilder.getErrorInfo(request);
        log.error("error>HTML: {}", errorInfo);
        response.sendRedirect("/error/index.html?status=" + errorInfo.getStatusCode());
    }

    @RequestMapping("${server.error.path:${error.path:/error}}")
    @ResponseBody
    @PermitAll
    public CommonResult<String> error(HttpServletRequest request, HttpServletResponse response) {
        ErrorInfoVO errorInfo = errorInfoBuilder.getErrorInfo(request);
        log.error("error>JSON: {}", errorInfo);
        response.setStatus(HttpStatus.OK.value());
        if (errorInfo.getError() instanceof ServiceException serviceException) {
            return CommonResult.error(serviceException.getCode(), serviceException.getMessage());
        }
        return CommonResult.error(errorInfo.getStatusCode(), errorInfo.getReasonPhrase());
    }

}
